package com.woniuxy.orderServer.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.json.JSONUtil;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.commons.exception.orderINfo.OrderInfoExceptionCode;
import com.woniuxy.commons.exception.orderINfo.OrderInfoException;
import com.woniuxy.commons.exception.sessionTicket.SessionTicketException;
import com.woniuxy.commons.exception.sessionTicket.SessionTicketExceptionCode;
import com.woniuxy.orderServer.config.AlipayConfiguration;
import com.woniuxy.orderServer.dao.OrderLogMapper;
import com.woniuxy.orderServer.model.OrderLog;
import com.woniuxy.orderServer.param.alipay.PagePayParam;
import com.woniuxy.commons.util.Result;
import com.woniuxy.commons.util.StateUtil;
import com.woniuxy.orderServer.client.ProductClient;
import com.woniuxy.orderServer.client.model.MovieSession;
import com.woniuxy.orderServer.client.model.SessionTicket;
import com.woniuxy.orderServer.dto.order.OrderInfoCreateDto;
import com.woniuxy.orderServer.dto.order.OrderProductDto;
import com.woniuxy.orderServer.model.OrderInfo;
import com.woniuxy.orderServer.dao.OrderInfoMapper;
import com.woniuxy.orderServer.param.order.OrderCreatParam;
import com.woniuxy.orderServer.service.OrderInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.orderServer.util.AlipayUtil;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 杜岷芫
 * @since 2024年03月20日
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private ProductClient productClient;
    @Autowired
    private AlipayUtil alipayUtil;
    @Autowired
    private AlipayConfiguration alipayConfiguration;
    @Autowired
    private OrderLogMapper orderLogMapper;

    @Override
    @Transactional
    public OrderInfoCreateDto createOrder(OrderCreatParam param) throws Exception{

        //判断座位
        Set<Integer> collect = param.getTicketIds().stream().collect(Collectors.toSet());
        List<Integer> ticketIds = new ArrayList<>(collect);

        Result<List<SessionTicket>> listResult = productClient.loadSessionTicketsByIds(ticketIds);
        if (listResult.getCode()!=200) throw  new SessionTicketException(listResult.getCode(),listResult.getMsg());
        Set<Integer> sessionIds= listResult.getData().stream().map(o -> o.getSessionId()).collect(Collectors.toSet());
        if (sessionIds.size()!=1) throw new SessionTicketException(SessionTicketExceptionCode.SESSION_TICKET_NOT_SAME_SESSION);
        if (ticketIds.size()!=listResult.getData().size()) throw new SessionTicketException(SessionTicketExceptionCode.SESSION_TICKET_NOT_ALL_TICKETS);
        //加锁
        System.out.println("#####");
//        ArrayList<RLock> rLocks = new ArrayList<>();
//        for (Integer ticketId : param.getTicketIds().stream().collect(Collectors.toSet())) {
//            RLock fairLock = redissonClient.getFairLock(RedisKeyUtil.lockTicketId(ticketId));
//            rLocks.add(fairLock);
//        }
//        System.out.println("!!!!!!!");
//        // 生成多锁
//        RLock[] lockArray = rLocks.toArray(new RLock[0]);
//        RLock lock = redissonClient.getMultiLock(lockArray);
//        lock.lock();//无限等待，开启看门狗

        //判断座位是否都可以购买
        Result<MovieSession> movieSessionResult = productClient.loadMovieSessionById((new ArrayList<Integer>(sessionIds)).get(0));
        if (movieSessionResult.getCode()!=200) throw new SessionTicketException(movieSessionResult.getCode(),movieSessionResult.getMsg());
        MovieSession movieSession = movieSessionResult.getData();
        if (movieSession==null||movieSession.getSessionStatus()!= StateUtil.MOVIE_SESSION_STATE_NORMAL);
        if (DateUtil.parse(movieSession.getSessionStarttime(),"yyyy-MM-dd HH:mm:ss").before(new Date()))
            throw new SessionTicketException(SessionTicketExceptionCode.SESSION_TICKET_SESSION_HAD_STARTED);
        //修改成锁定状态
        Result<Boolean> booleanResult = productClient.updateSessionTicketsByIds(ticketIds);
        if (booleanResult.getCode()!=200) throw new SessionTicketException(booleanResult.getCode(),booleanResult.getMsg());
        if (!booleanResult.getData()) throw new SessionTicketException(SessionTicketExceptionCode.SESSION_TICKET_UPDATE_TICKET_STATE_ERROR);

        //创建订单对象，保存
        OrderInfo orderInfo = new OrderInfo();
        Snowflake snowflake = new Snowflake(1, 1);
        String idStr = snowflake.nextIdStr();
        orderInfo.setOrderNum(idStr);
        orderInfo.setOrderState(StateUtil.ORDER_STATE_NOMAL);
        orderInfo.setOrderPaystate(0);
        orderInfo.setOrderTime(DateUtil.format(LocalDateTime.now(),"yyyy-MM-dd HH:mm:ss"));
        orderInfo.setOrderUser(param.getPhone());
        orderInfo.setOrderPrice(movieSession.getSessionPrice().multiply(new BigDecimal(ticketIds.size())));
        ArrayList<String> seats = new ArrayList<>();
        for (SessionTicket ticket : listResult.getData()) {
            seats.add(ticket.getSeatRow()+"排 "+ticket.getSeatCol()+"列");
        }
        orderInfo.setOrderProduct(JSONUtil.parse(seats).toString());
        OrderProductDto productDto = new OrderProductDto();
        productDto.setCinemaName(movieSession.getCinemaName());
        productDto.setMovieName(movieSession.getMovieName());
        productDto.setEndtime(movieSession.getSessionEndtime());
        productDto.setStarttime(movieSession.getSessionStarttime());
        productDto.setSeats(seats);
        orderInfo.setOrderProduct(JSONUtil.parse(productDto).toString());
        save(orderInfo);
        OrderInfoCreateDto orderInfoCreateDto = new OrderInfoCreateDto();
        orderInfoCreateDto.setOrderNUm(idStr);
        orderInfoCreateDto.setOrderPrice(orderInfo.getOrderPrice());
        orderInfoCreateDto.setOrderProductDto(productDto);
        orderInfoCreateDto.setOrderStatus(orderInfo.getOrderState());
        orderInfoCreateDto.setOrderUser(orderInfo.getOrderUser());
        //记录日志
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderNum(idStr);
        orderLog.setOrderNum(param.getPhone());
        orderLog.setLogTime(DateUtil.format(LocalDateTime.now(),"yyyy-MM-dd HH:mm:ss"));
        orderLog.setLogDesc("生产订单");
        orderLogMapper.insert(orderLog);
        //延迟消息


        return orderInfoCreateDto;
    }

    @Override
    public String payOrder(String orderNum) throws Exception{
        //查，判断
        OrderInfo orderInfo = this.getById(orderNum);
        if (orderInfo == null)
            throw new OrderInfoException(OrderInfoExceptionCode.ORDER_INFO_ORDER_NOT_EXIST);
        if (orderInfo.getOrderState() != StateUtil.ORDER_STATE_NOMAL)
            throw new OrderInfoException(OrderInfoExceptionCode.ORDER_INFO_STATE_ERROR);
//        if (!redisUtil.hasKey(RedisKeyUtil.payOrderTime(orderId))) throw new Exception("订单已超时");
//        long time = Long.parseLong(redisUtil.getObject(RedisKeyUtil.payOrderTime(orderId)).toString());
//        long now = new Date().getTime();
//        if ((time - now) / 1000 < 60) throw new Exception("订单已超时");

        PagePayParam param = new PagePayParam();
        //以下参数根据实际情况设置l
        param.setMoney(orderInfo.getOrderPrice().doubleValue());
        param.setSubject("订单支付");
        param.setBody("");
        param.setReturnUrl("https://www.woniuxy.com/");
        param.setNotifyUrl("http://hqqp4y.natappfree.cc/order/orderInfo/notify");
        param.setPayTimeBorder(15);
        param.setOrderId(orderNum);

        String page = alipayUtil.pagePay(param);
        return page;
    }

    @Override
    public void payNotify(HashMap<String, String> params) throws Exception{
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfiguration.getAlipayPublicKey(), "utf-8", "RSA2");
        if (!signVerified) throw new Exception("支付宝验签不通过");
        String orderId = params.get("out_trade_no");
        String tradeStatus = params.get("trade_status");
        String payTime = params.get("gmt_payment");

        //更新
        System.out.println("2024.2024");
        if ("TRADE_SUCCESS".equals(tradeStatus)) {
            System.out.println("2025.2025");
            OrderInfo orderInfo = this.getById(orderId);
            //修改订单状态
            orderInfo.setOrderState(StateUtil.ORDER_STATE_BUYED);
            orderInfo.setOrderPaystate(StateUtil.ORDER_STATE_BUYED);
            //支付时间
            LocalDateTime localDateTime = LocalDateTime.parse(payTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            orderInfo.setOrderPaytime(localDateTime);
            this.updateById(orderInfo);
            OrderLog orderLog = new OrderLog();
            orderLog.setOrderNum(orderInfo.getOrderNum());
            orderLog.setLogUser(orderInfo.getOrderUser());
            orderLog.setLogTime(DateUtil.format(LocalDateTime.now(),"yyyy-MM-dd HH:mm:ss"));
            orderLog.setLogDesc("支付订单");
            orderLogMapper.insert(orderLog);
        }
    }
}
